home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / src / transport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-02  |  28.2 KB  |  1,044 lines

  1. /* @(#)src/transport.c    1.22 8/3/92 04:48:37 */
  2.  
  3. /*
  4.  *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
  5.  *    Copyright (C) 1992  Ronald S. Karr
  6.  * 
  7.  * See the file COPYING, distributed with smail, for restriction
  8.  * and warranty information.
  9.  */
  10.  
  11. /*
  12.  * transport.c:
  13.  *    process and deliver remote addresses.
  14.  *
  15.  *    The routines in this file are used after an address has been
  16.  *    routed and resolved and associated with a particular transport.
  17.  *    This file provides some support routines for transport drivers.
  18.  *
  19.  *    external functions:  assign_transports, call_transports,
  20.  *                 write_message, remote_from_line, local_from_line,
  21.  *                 find_transport, find_transport_driver
  22.  */
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include <sys/param.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include "defs.h"
  29. #include "smail.h"
  30. #include "addr.h"
  31. #include "transport.h"
  32. #include "log.h"
  33. #include "spool.h"
  34. #include "dys.h"
  35. #include "exitcodes.h"
  36. #include "smailconf.h"
  37. #include "parse.h"
  38. #ifndef DEPEND
  39. # include "extern.h"
  40. # include "debug.h"
  41. # include "error.h"
  42. #endif
  43.  
  44. #ifdef    UNIX_BSD
  45. # include <sys/file.h>
  46. #endif
  47.  
  48. /* variables exported from this file */
  49. char *path_to_sender = NULL;        /* uucp-style route to sender */
  50. int cached_transports = FALSE;        /* TRUE if cache_transports() called */
  51.  
  52. /* functions local to this file */
  53. static int assign_compare();
  54. static int write_bsmtp_prologue();
  55. static int write_bsmtp_epilogue();
  56. static void build_path_to_sender();
  57. static char *tp_remove_header();
  58. static char *tp_insert_header();
  59. static char *tp_append_header();
  60. static char *transport_driv_function();
  61.  
  62.  
  63. /*
  64.  * assign_transports - assign instances of transports for addresses
  65.  *
  66.  * given a list of addresses as input, produce a list assigning a list
  67.  * of remote addresses to specific instances of a transport.  One
  68.  * instance essentially maps onto exactly one call to the underlying
  69.  * transport driver.
  70.  *
  71.  * NOTE:  This routine breaks the forward links between addr structures.
  72.  */
  73. struct assign_transport *
  74. assign_transports(list)
  75.     struct addr *list;            /* list of addresses */
  76. {
  77.     extern void qsort();
  78.     register struct addr *aq;        /* temp */
  79.     register struct assign_transport *asn; /* list of assigned transports */
  80.     register struct addr **aap;        /* points to array for sorting */
  81.     register int i;            /* index */
  82.     int ct;                /* count of items in input list */
  83.     int host_ct;            /* count of hosts in instance */
  84.     int addr_ct;            /* count of addrs in instance */
  85.     int char_ct = 0;            /* count of chars in instance */
  86.     struct transport *last_transport = NULL; /* last assigned transport */
  87.     char *last_host;            /* last assigned host */
  88.  
  89.     /* count the number of input items */
  90.     for (ct = 0, aq = list; aq; aq = aq->succ) {
  91.     ct++;
  92.     }
  93.  
  94.     DEBUG1(DBG_REMOTE_HI, "assign_transports called with %d addrs\n", ct);
  95.     /* create an array and copy remote information to it for sorting */
  96.     aap = (struct addr **)xmalloc(ct * sizeof(*aap));
  97.     for (aq = list, i = 0; aq; aq = aq->succ, i++) {
  98.     aap[i] = aq;
  99.     }
  100.  
  101.     /* NOTE: qsort does not appear to return anything */
  102.     qsort((char *)aap, ct, sizeof(*aap), assign_compare);
  103.  
  104.     /*
  105.      * we now have an array sorted by transport and host.
  106.      * pass through that array and assign addr structures to
  107.      * specific transport instances, taking into account
  108.      * max_addr and max_hosts for the transports.
  109.      */
  110.     for (asn = NULL, i = ct-1; i >= 0; --i) {
  111.     /* possible reasons to switch to a new instance */
  112.     if (
  113.         /* we have a different transport */
  114.         aap[i]->transport != last_transport ||
  115.  
  116.         /* maximum number of hosts per transport call exceeded */
  117.         (last_transport->max_hosts &&
  118.           aap[i]->next_host && last_host &&
  119.           !EQIC(aap[i]->next_host, last_host) &&
  120.           last_transport->max_hosts < ++host_ct) ||
  121.  
  122.         /* maximum number of addrs per transport call exceeded */
  123.         (last_transport->max_addrs &&
  124.           last_transport->max_addrs < ++addr_ct) ||
  125.  
  126.         /* maximum number of chars of addr per call exceeded */
  127.         (last_transport->max_chars &&
  128.           last_transport->max_chars <
  129.            (char_ct += (int)strlen(aap[i]->next_addr) + 3)))
  130.     {
  131.         /* initialize for a new instance */
  132.         struct assign_transport *newasn;
  133.  
  134.         DEBUG1(DBG_REMOTE_HI, "new instance ... transport=<%s>\n",
  135.            aap[i]->transport->name);
  136.         newasn = (struct assign_transport *)xmalloc(sizeof(*newasn));
  137.         last_transport = aap[i]->transport;
  138.         last_host = aap[i]->next_host;
  139.         host_ct = 1;
  140.         addr_ct = 1;
  141.         char_ct = strlen(aap[i]->next_addr) + 3;
  142.         /* fill in the first entry of the instance */
  143.         aap[i]->succ = NULL;
  144.         newasn->succ = asn;
  145.         asn = newasn;
  146.     } else {
  147.         /* add the addr to the previous instance */
  148.         aap[i]->succ = asn->addr;
  149.     }
  150.     asn->addr = aap[i];
  151.     DEBUG2(DBG_REMOTE_HI, "adding...host=<%s>, addr=<%s>\n",
  152.            asn->addr->next_host, asn->addr->next_addr);
  153.     }
  154.  
  155.     /* all done, free temps and return the list */
  156.     xfree((char *)aap);
  157.     return asn;
  158. }
  159.  
  160. /*
  161.  * compare two struct addrs for transport and then hostname
  162.  */
  163. static int
  164. assign_compare(a, b)
  165.     struct addr **a;
  166.     struct addr **b;
  167. {
  168.     register int ret = strcmp((*a)->transport->name, (*b)->transport->name);
  169.  
  170.     if (ret) {
  171.     /* transports are unequal, return value just based on that */
  172.     return ret;
  173.     }
  174.  
  175.     /* if next_host not defined, the addrs are equal */
  176.     if ((*a)->next_host == NULL || (*b)->next_host == NULL) {
  177.     return 0;
  178.     }
  179.  
  180.     /* otherwise, return value is based on host */
  181.     return strcmpic((*a)->next_host, (*b)->next_host);
  182. }
  183.  
  184.  
  185. /*
  186.  * call_transports - call transport drivers for assigned transports
  187.  *
  188.  * given a list produced by assign_transports, call the transport drivers
  189.  * to actually perform delivery to addresses.
  190.  */
  191. void
  192. call_transports(asn, defer, fail)
  193.     register struct assign_transport *asn; /* list of assigned instances */
  194.     struct addr **defer;        /* addrs to defer to a later time */
  195.     struct addr **fail;            /* unresolvable addrs */
  196. {
  197.     struct addr *succeed;        /* succeeded addrs from drivers */
  198.     struct addr *tp_defer;        /* defer addrs from drivers */
  199.     struct addr *tp_fail;        /* fail addrs from drivers */
  200.     struct addr *shadow_list = NULL;    /* shadow delivery list */
  201.     struct assign_transport *sh_asn;    /* shadow transport instances */
  202.  
  203.     for (; asn; asn = asn->succ) {
  204.     time_t started;
  205.     struct transport_driver *driver;
  206.     register struct transport *tp = asn->addr->transport;
  207.  
  208.     /*
  209.      * don't deliver to remote transports if the hop_count would
  210.      * pass beyond maximum.
  211.      */
  212.     if (hop_count >= max_hop_count && !(tp->flags&LOCAL_TPORT)) {
  213.         /*
  214.          * ERR_145 - maximum hop count exceeded
  215.          *
  216.          * DESCRIPTION
  217.          *      If a remote transport were performed, the maximum hop
  218.          *      count, as set by the max_hop_cound attribute in the
  219.          *      config file, would be exceeded.  This condition is
  220.          *      assumed to be a result of a loop condition where two
  221.          *      machines are sending mail back and forth to each other.
  222.          *
  223.          * ACTIONS
  224.          *      An error message is sent back to the sender stating the
  225.          *      error.  Note that if one of the sites back to the sender
  226.          *      has a shorter value for max_hop_count, then the error
  227.          *      message will fail to reach the sender though, hopefully,
  228.          *      a message will be sent back to the postmaster at the
  229.          *      local site.
  230.          *
  231.          * RESOLUTION
  232.          *      Determine which two sites are causing the loop condition
  233.          *      and remove or correct the forward or alias from one of
  234.          *      those two sites.  If the problem is not actually a loop
  235.          *      condition but a long path, a shorter path should be
  236.          *      used.  It is unlikely that paths longer than 10 or 15
  237.          *      hops should ever be required.
  238.          */
  239.         struct error *loop_error =
  240.         note_error(ERR_NSENDER|ERR_145,
  241.                "loop detection: maximum hop count exceeded");
  242.         register struct addr *cur;
  243.  
  244.         /* NOTE:  the sequence of operations here IS correct */
  245.         for (cur = asn->addr; cur; cur = cur->succ) {
  246.         cur->error = loop_error;
  247.         }
  248.         fail_delivery(asn->addr);
  249.         insert_addr_list(asn->addr, fail, loop_error);
  250.         continue;
  251.     }
  252.  
  253.     /* lookup the driver */
  254.     driver = find_transport_driver(tp->driver);
  255.  
  256.     if (driver == NULL) {
  257.         /* configuration error, the driver does not exist */
  258.         /*
  259.          * ERR_146 - transport driver not found
  260.          *
  261.          * DESCRIPTION
  262.          *      The driver name was not in the table of transport
  263.          *      drivers.
  264.          *
  265.          * ACTIONS
  266.          *      Defer addresses with configuration errors.
  267.          *
  268.          * RESOLUTION
  269.          *      The postmaster must check the transport configuration
  270.          *      before delivery can be performed.
  271.          */
  272.         insert_addr_list(asn->addr,
  273.                  defer,
  274.                  note_error(ERR_CONFERR|ERR_146,
  275.                     xprintf(
  276.                        "transport %s: driver %s not found",
  277.                         tp->name, tp->driver)));
  278.         continue;
  279.     }
  280.  
  281.     /* determine official time of attempt */
  282.     time(&started);
  283.  
  284.     /* call the transport */
  285.     succeed = NULL;
  286.     tp_defer = NULL;
  287.     tp_fail = NULL;
  288.  
  289.     DEBUG2(DBG_REMOTE_LO, "transport %s uses driver %s\n",
  290.            tp->name, tp->driver);
  291.     (*driver->driver)(asn->addr, &succeed, &tp_defer, &tp_fail);
  292.  
  293.     /* subject transport-deferred addresses to retry duration limits */
  294.     tp_defer = retry_addr_after(started, tp_defer, fail);
  295.  
  296.     /* look at successful deliveries */
  297.     if (succeed) {
  298.         retry_addr_finished(succeed);
  299.         /* log successes */
  300.         succeed_delivery(succeed);
  301.         if (tp->shadow) {
  302.         /* on successful delivery, call the shadow transport */
  303.         struct transport *shadow_tp = find_transport(tp->shadow);
  304.  
  305.         if (shadow_tp == NULL) {
  306.             send_to_postmaster = TRUE;
  307.             write_log(LOG_SYS|LOG_MLOG,
  308.                   "transport %s: shadow transport %s not found",
  309.                   tp->name, tp->shadow);
  310.         } else {
  311.             /* insert in shadow delivery list, with new transport */
  312.             register struct addr *cur;
  313.             register struct addr *next;
  314.  
  315.             for (cur = succeed; cur; cur = next) {
  316.             next = cur->succ;
  317.             cur->flags |= ADDR_SHADOW;
  318.             cur->transport = shadow_tp;
  319.             cur->succ = shadow_list;
  320.             shadow_list = cur;
  321.             }
  322.         }
  323.         }
  324.     }
  325.  
  326.     /* look at deferred deliveries */
  327.     if (tp_defer) {
  328.         retry_addr_finished(tp_defer);
  329.         insert_addr_list(tp_defer, defer, (struct error *)NULL);
  330.     }
  331.  
  332.     /* look at failed deliveries */
  333.     if (tp_fail) {
  334.         retry_addr_finished(tp_fail);
  335.         fail_delivery(tp_fail);    /* log them */
  336.         if (tp->error_transport == NULL) {
  337.         insert_addr_list(tp_fail, fail, (struct error *)NULL);
  338.         } else {
  339.         /* on failed delivery, call the error transport */
  340.         struct transport *error_tp =
  341.             find_transport(tp->error_transport);
  342.  
  343.         if (error_tp == NULL) {
  344.             send_to_postmaster = TRUE;
  345.             write_log(LOG_SYS|LOG_MLOG,
  346.                   "transport %s: error transport %s not found",
  347.                   tp->name, tp->error_transport);
  348.         } else {
  349.             /* insert in shadow delivery list, with new transport */
  350.             register struct addr *cur;
  351.             register struct addr *next;
  352.  
  353.             for (cur = tp_fail; cur; cur = next) {
  354.             next = cur->succ;
  355.             cur->transport = error_tp;
  356.             cur->succ = shadow_list;
  357.             shadow_list = cur;
  358.             }
  359.         }
  360.         }
  361.     }
  362.     }
  363.  
  364.     /* if there are shadow deliveries to be made, assign them and transport */
  365.     if (shadow_list == NULL) {
  366.     return;                /* no shadows, just return */
  367.     }
  368.  
  369.     /* assign shadow deliveries */
  370.     for (sh_asn = assign_transports(shadow_list);
  371.      sh_asn;
  372.      sh_asn = sh_asn->succ)
  373.     {
  374.     struct transport_driver *driver;
  375.     register struct transport *tp = sh_asn->addr->transport;
  376.     struct addr *dummy_defer;
  377.  
  378.     /* lookup the driver */
  379.     driver = find_transport_driver(tp->driver);
  380.  
  381.     if (driver == NULL) {
  382.         /* configuration error: for shadows, send to postmaster */
  383.         send_to_postmaster = TRUE;
  384.         write_log(LOG_SYS|LOG_MLOG,
  385.               "shadow transport %s: driver %s not found",
  386.               tp->name, tp->driver);
  387.         continue;
  388.     }
  389.  
  390.     /* call the shadow transport */
  391.     DEBUG2(DBG_REMOTE_LO, "calling driver %s from shadow transport %s\n",
  392.            tp->driver, tp->name);
  393.     succeed = NULL;
  394.     tp_fail = NULL;
  395.     (*driver->driver)(sh_asn->addr, &succeed, &dummy_defer, &tp_fail);
  396.  
  397.     /* log failed addresses */
  398.     if (fail) {
  399.         struct addr *cur;
  400.         struct addr *next;
  401.  
  402.         for (cur = tp_fail; cur; cur = next) {
  403.         next = cur->succ;
  404.         write_log(LOG_SYS, "%s ... shadow transport %s failed: %s",
  405.               cur->in_addr, cur->transport->name, cur->next_addr);
  406.         if ((cur->flags & ADDR_SHADOW) == 0) {
  407.             /*
  408.              * put failed deliveries from an error_transport on
  409.              * output fail list
  410.              */
  411.             cur->succ = *fail;
  412.             *fail = cur;
  413.         }
  414.         }
  415.     }
  416.     }
  417. }
  418.  
  419.  
  420. /*
  421.  * cache_transports - call cache entrypoints for all transports
  422.  *
  423.  * cache information used by transport drivers.  This can be called
  424.  * when it is determined that there will be an attempt to deliver more
  425.  * than one mail message, to increase the overall efficiency of the
  426.  * mailer.
  427.  *
  428.  * Daemons can call this periodically to recache stale data.
  429.  */
  430. void
  431. cache_transports()
  432. {
  433.     struct transport *tp;        /* temp for stepping thru transports */
  434.     struct transport_driver *driver;
  435.  
  436.     for (tp = transports; tp; tp = tp->succ) {
  437.     driver = find_transport_driver(tp->driver);
  438.     if (driver && driver->cache) {
  439.         (*driver->cache)(tp);
  440.     }
  441.     }
  442.     cached_transports = TRUE;
  443. }
  444.  
  445. #ifdef notyet
  446. /*
  447.  * finish_transports - free resources used by all directors
  448.  *
  449.  * free information that was cached by transports or used by
  450.  * transports in the process of delivering messages.  Transports can
  451.  * cache data for efficiency, or can maintain state between
  452.  * invocations.  This function is called when transports will no
  453.  * longer be needed, allowing transports to free any resources that
  454.  * they were using that will no longer be needed.  For example, it is
  455.  * a good idea for transports to close any files that they opened, as
  456.  * file descriptors are a precious resource in some machines.
  457.  */
  458. void
  459. finish_transports()
  460. {
  461.     struct transports *tp;        /* temp for stepping thru transports */
  462.     struct transport_driver *driver;
  463.  
  464.     for (tp = transports; tp; tp = tp->succ) {
  465.     driver = find_transport_driver(tp->driver);
  466.     if (driver->finish) {
  467.         (*driver->finish)(dp);
  468.     }
  469.     }
  470.     cached_transports = FALSE;
  471. }
  472. #endif
  473.  
  474.  
  475. /*
  476.  * write_message - write out the current message to an open file
  477.  *
  478.  * this takes a transport file entry and a list of addr structures
  479.  * and writes the message in the manner specified in the transport
  480.  * file entry.  It is intended to be called from transport drivers.
  481.  *
  482.  * If BSMTP_TPORT is set in the transport flags, an SMTP envelope
  483.  * is placed around the message.  However, result codes are not
  484.  * read from the destination so this is not useful for interactive
  485.  * SMTP.  The list of addr structures is only used for writing the
  486.  * SMTP envelope.  HBSMTP_TPORT generates an SMTP envelope without
  487.  * the initial HELO or the final QUIT commands.
  488.  *
  489.  * NOTE:  Everybody still needs to call fflush after calling
  490.  *      write_message().
  491.  *
  492.  * return READ_FAIL, WRITE_FAIL or SUCCEED
  493.  */
  494. int
  495. write_message(f, tp, addr)
  496.     FILE *f;                /* write on this file */
  497.     struct transport *tp;        /* transport file entry */
  498.     struct addr *addr;            /* list of addresses */
  499. {
  500.     int fail;                /* returned failure codes */
  501.  
  502.     DEBUG(DBG_HEADER_LO, "\nEnvelope text\n");
  503.     /*
  504.      * put out the initial smtp commands up to the DATA command
  505.      */
  506.     if (tp->flags & (BSMTP_TPORT | HBSMTP_TPORT)) {
  507. #ifndef NODEBUG
  508.     if (debug >= DBG_HEADER_LO && errfile) {
  509.         (void) write_bsmtp_prologue(errfile, tp, addr);
  510.     }
  511. #endif    /* NODEBUG */
  512.     if (write_bsmtp_prologue(f, tp, addr) == FAIL) {
  513.         return WRITE_FAIL;
  514.     }
  515.     tp->flags |= PUT_DOTS;        /* force use of SMTP dot protocol */
  516.     }
  517.  
  518.     /*
  519.      * write out a From<space> line, if required
  520.      */
  521.     if (tp->flags & PUT_FROM) {
  522.     /* but what form do we need? */
  523.     if (tp->flags & LOCAL_XFORM) {
  524. #ifndef NODEBUG
  525.         if (debug >= DBG_HEADER_LO && errfile) {
  526.         (void)fputs(local_from_line(), errfile);
  527.         }
  528. #endif    /* NODEBUG */
  529.         if (fputs(local_from_line(), f) == EOF) {
  530.         return WRITE_FAIL;
  531.         }
  532.     } else {
  533. #ifndef NODEBUG
  534.         if (debug >= DBG_HEADER_LO && errfile) {
  535.         (void)fputs(remote_from_line(), errfile);
  536.         }
  537. #endif    /* NODEBUG */
  538.         if (fputs(remote_from_line(), f) == EOF) {
  539.         return WRITE_FAIL;
  540.         }
  541.     }
  542.     DEBUG(DBG_HEADER_LO, "\n");
  543.     /* put the end of line */
  544.     if (tp->flags & PUT_CRLF) {
  545.         if (putc('\r', f) == EOF) {
  546.         return WRITE_FAIL;
  547.         }
  548.     }
  549.     if (putc('\n', f) == EOF) {
  550.         return WRITE_FAIL;
  551.     }
  552.     }
  553.  
  554.     /*
  555.      * write out the header according to the transport flags
  556.      */
  557.     if (write_header(f, addr) == FAIL) {
  558.     return WRITE_FAIL;
  559.     }
  560.     if ((tp->flags & PUT_CRLF) && putc('\r', f) == EOF) {
  561.     return WRITE_FAIL;
  562.     }
  563.     if (putc('\n', f) == EOF) {
  564.     return WRITE_FAIL;
  565.     }
  566.  
  567.     if (tp->flags & DEBUG_TPORT) {
  568.     /* if we are debugging, don't dump the body, dump interesting
  569.      * debugging info instead */
  570.     extern char **save_argv;    /* import this from main */
  571.     char **av;
  572.  
  573.     (void) fprintf(f, "|---- original flags ----|\n");
  574.     for (av = save_argv; *av; av++) {
  575.         (void) fprintf(f, "%s\n", *av);
  576.     }
  577.     (void) fprintf(f, "|---- interesting info ----|\n");
  578.     (void) fprintf(f,"\
  579.     message_id=%s\n\
  580.     spool_dir=%s\n\
  581.     spool_fn=%s\n\
  582.     transport=%s\n\
  583.     next_host=%s\n\
  584.     msg_grade=%c\n",
  585.                message_id,
  586.                spool_dir,
  587.                spool_fn,
  588.                tp->name,
  589.                (addr && addr->next_host)? addr->next_host: "(null)",
  590.                msg_grade);
  591.  
  592.     send_log(f, TRUE, "|---- per-message log ----|\n");
  593.     } else {
  594.  
  595.     DEBUG(DBG_HEADER_LO, "... message body ...\n");
  596.  
  597.     /*
  598.      * write out the body.
  599.      */
  600.     if ((fail = write_body(f, tp->flags)) != SUCCEED) {
  601.         return fail;
  602.     }
  603.     }
  604.  
  605.     /*
  606.      * finish off the SMTP envelope
  607.      */
  608.     if (tp->flags & (BSMTP_TPORT | HBSMTP_TPORT)) {
  609. #ifndef NODEBUG
  610.     if (debug >= DBG_HEADER_LO && errfile) {
  611.         (void) write_bsmtp_epilogue(errfile, tp, addr);
  612.     }
  613. #endif    /* NODEBUG */
  614.     if (write_bsmtp_epilogue(f, tp) == FAIL) {
  615.         return WRITE_FAIL;
  616.     }
  617.     }
  618.     DEBUG(DBG_HEADER_LO, "\n");
  619.  
  620.     return SUCCEED;            /* everything went fine */
  621. }
  622.  
  623. /*
  624.  * write_bsmtp_prologue - write the initial SMTP commands for BSMTP transports
  625.  *
  626.  * write out the HELO, MAIL FROM, RCPT TO and DATA commands.
  627.  */
  628. static int
  629. write_bsmtp_prologue(f, tp, addr)
  630.     FILE *f;                /* file to write commands to */
  631.     struct transport *tp;        /* transport entry */
  632.     struct addr *addr;            /* recipient addr structures */
  633. {
  634.     /*
  635.      * how do we end a line?
  636.      */
  637.     char *eol = (tp->flags & PUT_CRLF)? "\r\n": "\n";
  638.     char *error;
  639.  
  640.     if (! (tp->flags & HBSMTP_TPORT) &&
  641.     fprintf(f, "HELO %s%s", primary_name, eol) == EOF)
  642.     {
  643.     return FAIL;
  644.     }
  645.  
  646.     /*
  647.      * determine which sender form is appropriate
  648.      */
  649.     if (error_sender) {
  650.     /* if the special SMTP sender forms <> or <+> were given, pass along */
  651.     if (fprintf(f, "MAIL FROM:<%s>%s",
  652.             ((islocal && tp->flags & LOCAL_XFORM)? "+": ""),
  653.             eol) == EOF) {
  654.         return FAIL;
  655.     }
  656.     } else {
  657.     if (fprintf(f, "MAIL FROM:<%s>%s", get_sender_addr(tp), eol) == EOF) {
  658.         return FAIL;
  659.     }
  660.     }
  661.  
  662.     /*
  663.      * write out a RCPT TO: line for each recipient address
  664.      */
  665.     while (addr) {
  666.     if (fprintf(f, "RCPT TO:<%s>%s", addr->next_addr, eol) == EOF) {
  667.         return FAIL;
  668.     }
  669.     addr = addr->succ;
  670.     }
  671.  
  672.     if (fprintf(f, "DATA%s", eol) == EOF) {
  673.     return FAIL;
  674.     }
  675.  
  676.     return SUCCEED;
  677. }
  678.  
  679. /*
  680.  * get_sender_addr - return a sender address for use a particular transport
  681.  *
  682.  * Return a transformation of the sender address based on the various
  683.  * transport attributes.
  684.  *
  685.  * The returned storage should not be freed and may be reused in
  686.  * subsequent calls to get_sender_addr.
  687.  */
  688. char *
  689. get_sender_addr(tp)
  690.     struct transport *tp;
  691. {
  692.     static struct str str;
  693.     static int inited = 0;
  694.     char *path;
  695.     int form;
  696.     int flags;
  697.     char *err;
  698.  
  699.     if (! inited) {
  700.     inited = 1;
  701.     STR_INIT(&str);
  702.     } else {
  703.     str.i = 0;
  704.     }
  705.  
  706.     if (tp->flags & UUCP_XFORM ||
  707.     (tp->flags & PUT_FROM && !(tp->flags & LOCAL_XFORM)))
  708.     {
  709.     path = build_partial_uucp_route(sender, &err, 0);
  710.     if (path) {
  711.         str_printf(&str, "%s!%s%N", uucp_name, path);
  712.         xfree(path);
  713.     } else {
  714.  
  715.         /*
  716.          * bad sender path, prepend host! anyway.
  717.          */
  718.  
  719.         str_printf(&str, "%s!%s%N", uucp_name, sender);
  720.     }
  721.  
  722.     return str.p;
  723.     }
  724.  
  725.     if (tp->flags & LOCAL_XFORM) {
  726.     return sender;
  727.     }
  728.  
  729.  
  730.     /* INET_XFORM or no specified transform */
  731.     form = parse_address(sender, (char **)0, &err, &flags);
  732.     switch (form) {
  733.     case FAIL:
  734.     case RFC_ROUTE:
  735.     case RFC_ENDROUTE:
  736.     case MAILBOX:
  737.     case PARSE_ERROR:
  738.     return sender;
  739.  
  740.     default:
  741.     str_printf(&str, "%s@%s%N", sender, visible_name);
  742.     return str.p;
  743.     }
  744. }
  745.  
  746. /*
  747.  * write_bsmtp_epilogue - write tailing commands for BSMTP transports
  748.  *
  749.  * finish off the data command and write out the QUIT command.
  750.  */
  751. static int
  752. write_bsmtp_epilogue(f, tp)
  753.     FILE *f;
  754.     struct transport *tp;
  755. {
  756.     if (tp->flags & HBSMTP_TPORT) {
  757.     if (fprintf(f, (tp->flags&PUT_CRLF)? ".\r\n": ".\n") == EOF) {
  758.         return FAIL;
  759.     }
  760.     return SUCCEED;
  761.     }
  762.     if (tp->flags & PUT_CRLF) {
  763.     if (fprintf(f, ".\r\nQUIT\r\n") == EOF) {
  764.         return FAIL;
  765.     }
  766.     } else {
  767.     if (fprintf(f, ".\nQUIT\n") == EOF) {
  768.         return FAIL;
  769.     }
  770.     }
  771.  
  772.     return SUCCEED;
  773. }
  774.  
  775.  
  776. /*
  777.  * remote_from_line - build a From_ line for remote transports
  778.  */
  779. char *
  780. remote_from_line()
  781. {
  782.     static char *from_line = NULL;    /* saved From_ line */
  783.  
  784.     if (from_line) {
  785.     return from_line;        /* exists, use it */
  786.     }
  787.     if (path_to_sender == NULL) {
  788.     build_path_to_sender();
  789.     }
  790.     from_line = xprintf("From %s %s remote from %s",
  791.             path_to_sender, unix_date(), uucp_name);
  792.     return from_line;
  793. }
  794.  
  795. /*
  796.  * local_from_line - build a From_ line for local transports
  797.  */
  798. char *
  799. local_from_line()
  800. {
  801.     static char *from_line = NULL;    /* saved From_ line */
  802.  
  803.     if (from_line) {
  804.     return from_line;        /* exists, use it */
  805.     }
  806.     if (path_to_sender == NULL) {
  807.     build_path_to_sender();
  808.     }
  809.     from_line = xprintf("From %s %s", path_to_sender, unix_date());
  810.     return from_line;
  811. }
  812.  
  813. /*
  814.  * build_path_to_sender - build a !-route version of sender address
  815.  */
  816. static void
  817. build_path_to_sender()
  818. {
  819.     char *error;
  820.  
  821.     path_to_sender = build_partial_uucp_route(sender, &error);
  822.     if (path_to_sender == NULL) {
  823.     write_log(LOG_SYS|LOG_MLOG,
  824.           "error building path to sender, sender=%s, error=%s",
  825.           sender, error);
  826.     path_to_sender = "Postmaster";
  827.     }
  828. }
  829.  
  830.  
  831. /*
  832.  * find_transport - given a transport's name, return the transport structure
  833.  *
  834.  * return NULL if no transport of that name exists.
  835.  */
  836. struct transport *
  837. find_transport(name)
  838.     register char *name;        /* search key */
  839. {
  840.     register struct transport *tp;    /* temp for stepping thru transports */
  841.  
  842.     /* loop through all the transports */
  843.     for (tp = transports; tp; tp = tp->succ) {
  844.     if (EQ(tp->name, name)) {
  845.         /* found the transport in question */
  846.         return tp;
  847.     }
  848.     }
  849.  
  850.     return NULL;            /* transport not found */
  851. }
  852.  
  853. /*
  854.  * find_transport_driver - given a driver's name, return the driver structure
  855.  *
  856.  * return NULL if driver does not exist.
  857.  */
  858. struct transport_driver *
  859. find_transport_driver(name)
  860.     register char *name;        /* search key */
  861. {
  862.     register struct transport_driver *tdp; /* pointer to table of drivers */
  863.  
  864.     for (tdp = transport_drivers; tdp->name; tdp++) {
  865.     if (EQ(tdp->name, name)) {
  866.         return tdp;            /* found the driver */
  867.     }
  868.     }
  869.  
  870.     return NULL;            /* driver not found */
  871. }
  872.  
  873.  
  874. /*
  875.  * read_transport_file - read transport file
  876.  *
  877.  * read the transport file and build the transport list describing the
  878.  * entries.  Return an error message or NULL.
  879.  *
  880.  * The entries from the transport file are prepended to the built-in
  881.  * transports.
  882.  */
  883. char *
  884. read_transport_file()
  885. {
  886.     FILE *f;                /* open transport file */
  887.     char *error;            /* error from read_standard_file() */
  888.     struct transport **tpp;
  889.     struct stat statbuf;
  890.     static struct attr_table transport_generic[] = {
  891.     { "driver", t_string, NULL, NULL, OFFSET(transport, driver) },
  892.     { "max_addrs", t_int, NULL, NULL, OFFSET(transport, max_addrs) },
  893.     { "max_hosts", t_int, NULL, NULL, OFFSET(transport, max_hosts) },
  894.     { "max_chars", t_int, NULL, NULL, OFFSET(transport, max_chars) },
  895.     { "retry_dir", t_string, NULL, NULL, OFFSET(transport, retry_dir) },
  896.     { "shadow", t_string, NULL, NULL, OFFSET(transport, shadow) },
  897.     { "error_transport", t_string, NULL, NULL,
  898.       OFFSET(transport, error_transport) },
  899.     { "strict", t_boolean, NULL, NULL, STRICT_TPORT },
  900.     { "uucp", t_boolean, NULL, NULL, UUCP_XFORM },
  901.     { "inet", t_boolean, NULL, NULL, INET_XFORM },
  902.     { "received", t_boolean, NULL, NULL, PUT_RECEIVED },
  903.     { "return_path", t_boolean, NULL, NULL, PUT_RETURNPATH },
  904.     { "from", t_boolean, NULL, NULL, PUT_FROM },
  905.     { "local", t_boolean, NULL, NULL, LOCAL_TPORT|LOCAL_XFORM },
  906.     { "local_xform", t_boolean, NULL, NULL, LOCAL_XFORM },
  907.     { "crlf", t_boolean, NULL, NULL, PUT_CRLF },
  908.     { "bsmtp", t_boolean, NULL, NULL, BSMTP_TPORT },
  909.     { "hbsmtp", t_boolean, NULL, NULL, HBSMTP_TPORT },
  910.     { "dots", t_boolean, NULL, NULL, PUT_DOTS },
  911.     { "debug", t_boolean, NULL, NULL, DEBUG_TPORT },
  912.     { "unix_from_hack", t_boolean, NULL, NULL, UNIX_FROM_HACK },
  913.     { "uucp_from_hack", t_boolean, NULL, NULL, UNIX_FROM_HACK },
  914.     { "remove_header", t_proc, NULL, (tup *)tp_remove_header, 0 },
  915.     { "insert_header", t_proc, NULL, (tup *)tp_insert_header, 0 },
  916.     { "append_header", t_proc, NULL, (tup *)tp_append_header, 0 },
  917.     };
  918.     struct attr_table *end_transport_generic = ENDTABLE(transport_generic);
  919.     static struct transport transport_template = {
  920.     NULL,                /* name */
  921.     "pipe",                /* driver, a reasonable default */
  922.     NULL,                /* succ will be assigned */
  923.     PUT_RECEIVED,            /* flags */
  924.     1,                /* max_addrs */
  925.     1,                /* max_hosts */
  926.     2000,                /* max_chars, about half of NCARGS? */
  927.     NULL,                /* shadow */
  928.     NULL,                /* error_transport */
  929.     NULL,                /* private */
  930.     };
  931.  
  932.     /*
  933.      * try to open the transport file, stat file if possible
  934.      */
  935.     if (transport_file == NULL || EQ(transport_file, "-")) {
  936.     return NULL;
  937.     }
  938.     f = fopen(transport_file, "r");
  939.     if (f == NULL) {
  940.     if (require_configs) {
  941.         return xprintf("%s: %s", transport_file, strerrno());
  942.     }
  943.  
  944.     add_config_stat(transport_file, (struct stat *)NULL);
  945.     return NULL;
  946.     }
  947.  
  948.     (void)fstat(fileno(f), &statbuf);
  949.     add_config_stat(transport_file, &statbuf);
  950.  
  951.     /* call read_standard_file to do the real work */
  952.     error = read_standard_file(f,
  953.                    (char *)&transport_template,
  954.                    sizeof(struct transport),
  955.                    OFFSET(transport, name),
  956.                    OFFSET(transport, flags),
  957.                    OFFSET(transport, succ),
  958.                    transport_generic,
  959.                    end_transport_generic,
  960.                    transport_driv_function,
  961.                    (char **)&transports);
  962.  
  963.     /* finish up */
  964.     (void) fclose(f);
  965.  
  966.     for (tpp = &transports; *tpp; tpp = &(*tpp)->succ)
  967.     ;
  968.     *tpp = builtin_transports;
  969.  
  970.     /* return any error message */
  971.     if (error) {
  972.     return xprintf("%s: %s", transport_file, error);
  973.     }
  974.     return NULL;
  975. }
  976.  
  977. static char *
  978. tp_remove_header(struct_p, attr)
  979.     char *struct_p;            /* passed transport structure */
  980.     struct attribute *attr;        /* attribute from transports file */
  981. {
  982.     struct transport *tp = (struct transport *)struct_p;
  983.     struct list *lp;
  984.  
  985.     lp = (struct list *)xmalloc(sizeof(*lp));
  986.     lp->text = attr->value;
  987.     lp->succ = tp->hdrremove;
  988.     tp->hdrremove = lp;
  989.     return NULL;
  990. }
  991.  
  992. static char *
  993. tp_insert_header(struct_p, attr)
  994.     char *struct_p;            /* passed transport structure */
  995.     struct attribute *attr;        /* attribute from transports file */
  996. {
  997.     struct transport *tp = (struct transport *)struct_p;
  998.     struct list *lp;
  999.  
  1000.     lp = (struct list *)xmalloc(sizeof(*lp));
  1001.     lp->text = attr->value;
  1002.     lp->succ = tp->hdrinsert;
  1003.     tp->hdrinsert = lp;
  1004.     return NULL;
  1005. }
  1006.  
  1007. static char *
  1008. tp_append_header(struct_p, attr)
  1009.     char *struct_p;            /* passed transport structure */
  1010.     struct attribute *attr;        /* attribute from transports file */
  1011. {
  1012.     struct transport *tp = (struct transport *)struct_p;
  1013.     struct list *lp;
  1014.  
  1015.     lp = (struct list *)xmalloc(sizeof(*lp));
  1016.     lp->text = attr->value;
  1017.     lp->succ = tp->hdrappend;
  1018.     tp->hdrappend = lp;
  1019.     return NULL;
  1020. }
  1021.  
  1022. static char *
  1023. transport_driv_function(struct_p, driver_attrs)
  1024.     char *struct_p;            /* passed transport structure */
  1025.     struct attribute *driver_attrs;    /* driver-specific attributes */
  1026. {
  1027.     struct transport *tp = (struct transport *)struct_p;
  1028.     struct transport_driver *drv;
  1029.  
  1030.     if (tp->driver == NULL) {
  1031.     return xprintf("transport %s: no driver attribute", tp->name);
  1032.     }
  1033.     drv = find_transport_driver(tp->driver);
  1034.     if (drv == NULL) {
  1035.     return xprintf("transport %s: unknown driver: %s",
  1036.                tp->name, tp->driver);
  1037.     }
  1038.     if (drv->builder) {
  1039.     return (*drv->builder)(tp, driver_attrs);
  1040.     }
  1041.  
  1042.     return NULL;
  1043. }
  1044.